import {
  Headers as Header,
  Interceptor,
  IPretendDecoder,
  Post,
  Pretend,
} from 'pretend';

/** 创建仓库参数 */
interface ICreateRepoParams {
  /** 用户授权码 */
  access_token: string;
  /** 仓库名 */
  name: string;
  /** 仓库描述 */
  description?: string;
  homepage?: string;
  has_issues?: boolean;
  has_wiki?: boolean;
  can_comment?: boolean;
  auto_init?: boolean;
  gitignore_template?: string;
  license_template?: string;
  /** 是否私有 */
  private?: boolean;
}

/** 创建代码片段参数 */
interface ICreateGistParams {
  /** 用户授权码 */
  access_token: string;
  /** Hash形式的代码片段文件名以及文件内容。如: { "file1.txt": { "content": "String file contents" } } */
  files: {
    [file: string]: {
      /** 文件内容 */
      content: string;
    }
  };
  /** 代码片段描述，1~30个字符 */
  description: string;
  /** 公开/私有，默认: 私有 */
  public?: boolean;
}

export interface Gitee {
  /** 创建仓库 */
  createRepository(body: ICreateRepoParams): Promise<any>;

  /** 创建代码片段 */
  createGist(body: ICreateGistParams): Promise<any>;
}

namespace impl {
  export class GiteeBlueprint implements Gitee {
    /**
     * doc: https://gitee.com/api/v5/swagger#/postV5UserRepos
     */
    @Header('Content-Type: application/json')
    @Post('/user/repos')
    public createRepository(_body: ICreateRepoParams): any { }

    /**
     * doc: https://gitee.com/api/v5/swagger#/postV5Gists
     */
    @Header('Content-Type: application/json')
    @Post('/gists')
    createGist(_body: ICreateGistParams): any { }
  }

  export function logger(logger: (message: string) => void): Interceptor {
    return async (chain, request) => {
      try {
        logger(`${request.options.method} ${request.url}`);
        // console.log('github-request: ', request);
        const response = await chain(request);
        // console.log('response', response);
        return response;
      } catch (e) {
        if ((e as GiteeError).response) {
          logger(`${(e as GiteeError).response.status} ${e.message}`);
        }
        throw e;
      }
    };
  }

  export class GiteeError extends Error {
    public readonly response: Response;

    constructor(message: string, response: Response) {
      super(message);
      this.response = response;
    }
  }

  export function giteeDecoder(): IPretendDecoder {
    return async response => {
      if (response.status >= 400) {
        const body = await response.json();
        throw new GiteeError(
          `${body.message || response.statusText}`,
          response
        );
      }
      const headers: { [key: string]: any } = {};
      response.headers.forEach((value, key) => {
        headers[key] = [...(headers[key] || []), value];
      });
      return {
        status: response.status,
        headers,
        body:
          response.status >= 200 && response.status <= 300
            ? await response.json()
            : undefined
      };
    };
  }
}

export function getClient(
  endpoint: string,
  // token: string,
  logger: (message: string) => void,
  // allowUnsafeSSL = false
): Gitee {
  return Pretend.builder()
    // .interceptor(impl.githubCache())
    // .requestInterceptor(impl.githubTokenAuthenticator(token))
    // .requestInterceptor(impl.githubHttpsAgent(!allowUnsafeSSL))
    .interceptor(impl.logger(logger))
    .decode(impl.giteeDecoder())
    .target(impl.GiteeBlueprint, endpoint);
}
